import os
import shutil
import sys
import threading
import tkinter as tk
from tkinter import filedialog, messagebox, scrolledtext
from typing import Final
from SmartBackup import SmartBackup
from tools import ThreadPoolManager

CHOOSE_SOURCE_STR: Final[str] = "请选择需要备份的文件目录"
CHOOSE_TARGET_STR: Final[str] = "请选择导出的文件目录"
CONFIG_FILE: Final[str] = "config.txt"
CONFIG_FILE_LOCAL: Final[str] = "config/"
CONFIG_FILE_LOCAL_PATH: Final[str] = CONFIG_FILE_LOCAL + CONFIG_FILE
CONFIG_FILE_USER: Final[str] = "C:\\Users\\admin\\AppData\\Local\\PythonUDiskSync\\config\\"
CONFIG_FILE_USER_PATH: Final[str] = CONFIG_FILE_USER + CONFIG_FILE


class MainWindow:
    def __init__(self):
        self.sourceFilePath = None
        self.targetFilePath = None
        root = self.createView()
        self.deleteDiff = tk.IntVar()
        self.createFileChooseView(root)
        self.createInfoList(root)
        # 加载本地用户数据，获取上一次备份过的目录
        data = self.loadConfig()
        if data.get('sourceFilePath'):
            self.sourceFilePath = data['sourceFilePath']
            self.sourceFile.config(text=self.sourceFilePath)
        if data.get('targetFilePath'):
            self.targetFilePath = data['targetFilePath']
            self.targetFile.config(text=self.targetFilePath)
        root.mainloop()  # 进入主事件循环

    # 创建主窗口
    def createView(self):
        root = tk.Tk()
        root.title("U盘备份助手")
        root.geometry("500x450")
        root.iconphoto(True, tk.PhotoImage(file=self.resource_path('./img/logo.png')))
        return root

    # 创建选择文件按钮控件
    def createFileChooseView(self, root):
        self.sourceFile = tk.Button(root, text=CHOOSE_SOURCE_STR, compound="center",
                                    command=self.chooseSourceFile)
        self.targetFile = tk.Button(root, text=CHOOSE_TARGET_STR, compound="center", command=self.chooseTargetFile)
        self.startBtn = tk.Button(root, text="开始备份", compound="center", command=self.startCopy)
        self.sourceFile.pack(pady=(20, 0))
        self.targetFile.pack(pady=(5, 0))
        self.deleteDiffBtn = tk.Checkbutton(root, text='是否删除源文件夹不存在的文件（谨慎勾选！！！）',
                                            variable=self.deleteDiff, onvalue=1, offvalue=0)
        self.deleteDiffBtn.pack(pady=(5, 0))
        self.startBtn.pack(pady=(10, 0))

    # 选择源文件夹
    def chooseSourceFile(self):
        self.sourceFilePath = self.openFileWindow(self.sourceFilePath)
        self.sourceFile.config(text=self.sourceFilePath)

    # 选择目标文件夹
    def chooseTargetFile(self):
        self.targetFilePath = self.openFileWindow(self.targetFilePath)
        self.targetFile.config(text=self.targetFilePath)

    # 尝试开始备份
    def startCopy(self):
        if self.sourceFilePath is None:
            self.showToastWindow(CHOOSE_SOURCE_STR + '!')
            return
        if self.targetFilePath is None:
            self.showToastWindow(CHOOSE_TARGET_STR + '!')
            return
        if self.targetFilePath == self.sourceFilePath:
            self.showToastWindow('两个目录不能相同!')
            return
        checkPass = True
        if self.deleteDiff.get() == 1:
            # 要求用户二次确认高危操作
            checkPass = messagebox.askokcancel("请注意确认！",
                                               "勾选删除操作会删除备份文件夹中在，而源文件夹中不存在的文件，您确定要继续吗？")
        if checkPass:
            self.saveConfig()
            threading.Thread(target=self.run, name='备份线程').start()

    # 拷贝过程放到子线程进行
    def run(self):
       self.backupFolder(self.sourceFilePath, self.targetFilePath)

    # 打开文件夹选择窗口
    def openFileWindow(self, filePath):
        if filePath is None:
            filePath = 'C:/'
        return filedialog.askdirectory(
            title='请选择文件夹',  # 设置对话框标题:cite[7]:cite[9]:cite[10]
            initialdir=filePath  # 设置初始目录，例如C盘根目录:cite[7]:cite[10]
        )

    # 显示错误信息提示弹窗
    def showToastWindow(self, infoStr):
        messagebox.showinfo(infoStr, infoStr)

    # 备份文件夹
    def backupFolder(self, src, dest):
        backup_system = SmartBackup(self,
                                    source_dir=src,
                                    backup_dir=dest
                                    )
        backup_system.backup( deleteDiff=self.deleteDiff.get() == 1)
        # 重置删除按钮选中状态，避免用户误操作
        self.deleteDiff.set(0)

    def consoleCallback(self, str, message_type="I"):
        # 插入控制台显示信息并自动显示最后一行
        self.console.insert('end', str + "\n")
        self.console.see('end')

    # 创建日志输出控件
    def createInfoList(self, frame):
        tk.Label(frame, text="系统信息").pack(pady=(20, 0))
        self.console = scrolledtext.ScrolledText(
            frame,
            wrap=tk.WORD,
            font=('Courier New', 9),
            bg='#eeeeee',  # 深色背景
            fg='#000000',
            insertbackground='white',
            width=80,
            height=25
        )
        self.console.pack(fill='both', expand=True, padx=10, pady=5)

    # 保存用户数据
    def saveConfig(self):
        self.console.insert('end', '配置保存路径：' + CONFIG_FILE_USER_PATH)
        with open(CONFIG_FILE_USER_PATH, "w", encoding='utf-8') as f:
            f.write('sourceFilePath*=' + self.sourceFilePath + '\n')
            f.write('targetFilePath*=' + self.targetFilePath + '\n')
            f.close()

    # 加载本地用户数据
    def loadConfig(self):
        if not os.path.exists(CONFIG_FILE_USER_PATH):
            try:
                os.makedirs(CONFIG_FILE_USER, exist_ok=True)
                shutil.copy2(str(self.resource_path(CONFIG_FILE_LOCAL_PATH)), CONFIG_FILE_USER_PATH)
            except Exception as e:
                print(f"配置文件复制失败: {e}")
            return {}
        data = []
        dataMap = {}
        with open(CONFIG_FILE_USER_PATH, "r", encoding='utf-8') as f:
            data = f.readlines()
            f.close()
        if len(data) == 0:
            return {}
        for d in data:
            key, value = d.split("*=")
            dataMap[key] = value.replace("\n", "")
        return dataMap

    def resource_path(self, relative_path):
        """ 获取资源的绝对路径。
        参数:
            relative_path (str): 资源的相对路径
        返回:
            str: 资源的绝对路径
        """
        try:
            # 打包后的临时文件夹
            base_path = sys._MEIPASS
        except AttributeError:
            # 正常运行的当前目录
            base_path = os.path.abspath(".")
        return os.path.join(base_path, relative_path)
